﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using YasharEl.Infrastructure.EntityModel.Specifications;
using YasharEl.Infrastructure.EntityModel;
using NHibernate;
using System.Linq.Expressions;

namespace YasharEl.Infrastructure.PersistenceModel.NHibernate.Specifications
{
    public abstract class QueryOverSpecification<TEntity, TIdentity> : ISpecification<TEntity, TIdentity>
        where TEntity : class, IGenericEntity<TIdentity>
    {
        /// <summary>
        /// Gets QueryOver specification.
        /// </summary>
        protected IQueryOver<TEntity, TEntity> QueryOver { get; private set; }
        protected IQueryable<TEntity> Query { get; private set; }

        #region Implementation of ISpecification<TEntity>

        /// <summary>
        /// Initializes specification from given unit of work instance.
        /// </summary>
        public void Initialize(IUnitOfWork unitOfWork)
        {
            Query = unitOfWork.ToQueryable<TEntity, TIdentity>();
            this.QueryOver = ((NHibernateUnitOfWork)unitOfWork).Session.QueryOver<TEntity>();
        }

        /// <summary>
        /// Gets specification result wrapped into <see cref="ISpecificationResult" />
        ///   interface.
        /// </summary>
        /// <remarks>
        /// <see cref="ISpecificationResult"/> interface wrapps common functionality that is shared
        /// accross all specifications.
        /// </remarks>
        public ISpecificationResult<TEntity, TIdentity> ToResult()
        {
            return new QueryOverSpecificationResult<TEntity, TIdentity>(this.QueryOver);
        }

        public ISpecification<TEntity, TIdentity> Where(Expression<Func<TEntity, bool>> expression)
        {
            this.QueryOver.Where(expression);
            return this;
        }

        #endregion
    }
}
